<template>
    <div class="app-container tz-app" style="overflow-y:hidden">
        <!-- 参数设置 -->
        <fParams @start="fullStart" @stop="fullStop" :isStart="isStart"></fParams>

        <div class="frequency-message">
            <div class="frequency-message-main" style="width: 100%;">
                <div class="headline-text">
                    <div class="h-text">射频直采数据</div>
                    <div class="h-button">
                        <div class="h-num flex">
                            <input class="h-num-input" type="number" v-model="frequencyNum" @blur="calculateWire" />MHz
                        </div>
                        <div :class="!isStart ? 'h-btn-n' : 'h-btn'" @click="belowAddPopUpData">下变频数据</div>
                    </div>
                </div>

                <div class="container" @click="showLineWay($event)">
                    <frequency style="width: 100%;" :inputData="frequencyData" height="550px" @setNumber="setNumber"
                        :frequencyNum="frequencyNumInput" :type="1">
                    </frequency>
                    <Heating style="width: 100%;" height="100px" :inputData="frequencyData"></Heating>
                </div>

            </div>

            <!-- <div class="frequency-message-minor" ref="componentContainer" v-if="popUpData[0]">
                <div style="height: 100%;">
                    <div class="frequency-headline">基础设置</div>
                    <data-set :inputData="popUpData[0].frequencyData" :id="popUpData[0].id"
                        @play="playStart" @go="go" :type="2" :isStart="isStart" :playCentral="playCentral">
                    </data-set>
                </div>
            </div> -->

        </div>

        <div v-for="(item, index) in popUpData" :key="index">
            <PopUp class="frequency-pop" :inputData="item.frequencyData" @closeDialog="channelObj=>{closeDialogPopUp(channelObj,index)}">
                <template v-slot:default>
                    <data-set :inputData="item.frequencyData" @play="playStart" @go="go" :id="item.id"
                        :isStart="isStart" :playCentral="playCentral"> </data-set>
                </template>
            </PopUp>
        </div>


        <!-- <min-dialog :title="frequencySet.title" width="450px" :visible="frequencySet.open"
            @closeDialog="frequencySet.open = false">
            <template v-slot:default>
                <div class="min-dialog" style="height: 250px;padding: 10px;margin-top: 40px;" v-if="frequencySet.open">
                    <el-form :model="frequencySet" label-width="120px">
                        <el-form-item label="采集宽带设置:">
                            <el-input class="zt-input" v-model="frequencySet.data[0].configValue" placeholder="采集宽带设置"
                                style="width: 250px;"></el-input>
                            MHZ
                        </el-form-item>
                        <el-form-item label="中心频率设置:">
                            <el-input class="zt-input" v-model="frequencySet.data[1].configValue" placeholder="中心频率设置"
                                style="width: 250px;"></el-input>
                            MHZ
                        </el-form-item>
                    </el-form>
                    <el-button class="bt-blue" style="margin-left: 250px;margin-top: 50px;"
                        @click="postParameter">确认</el-button>
                </div>
            </template>
        </min-dialog> -->

    </div>
</template>

<script>
import socketApi from '@/api/socketApi' // socketApi



import { ffbStop, ffbStart, channelStart, channelStop, playStart, playStop, recordStart, recordStop, sdrSet, queryParameter, editParameter } from "@/api/business/frequency";
import PopUp from "@/components/TZ/PopUp"
import PopUp2 from "@/components/TZ/PopUp2"
import PopUp3 from "@/components/TZ/PopUp3"
import Frequency from "@/components/TZ/Frequency"
import Heating from "@/components/TZ/Heating"
import DataSet from "@/components/TZ/DataSet"
import MinDialog from "@/components/TZ/MinDialog"
import { v4 as uuidv4 } from 'uuid';
import Decimal from 'decimal.js';
import { getRadioStationList } from "@/api/business/station";
import { base64PlayUrl } from "@/utils/transcoding"

import fParams from "./components/f-params.vue";
export default {
    components: { fParams, PopUp, Frequency, Heating, DataSet, MinDialog, PopUp2, PopUp3 },
    dicts: ['located_address'],
    name: "Room",
    data() {
        return {
            // socket连接对象
            ws: null,
            // SDR连接地址
            url: "ws://140.210.217.137:9208/websocket",
            // 是否启动了频谱
            isStart: false,
            // 频谱参数
            parmars: {},
            // 连接唯一标识
            socketId: null,
            // 当前开启的频谱
            startObj: null,
            // 固定参数数据
            sendParmars: {
                // 采样率
                sample_frequence: 2000000, type: "channel", "resolution_ratio": 3000, "points": 1024, "modem": "c0", "mode": "ssb"
            },
            // 全频段数据
            frequencyData: { central: 0, need_points: 0, bandwidth: 0, points: 0, data: "", },
            // 保存组件数据的数组
            popUpData: [],
            // 是否启动全频段
            isStart: false,
            // 是否播放音频
            audioPlay: false,
            // 音频播放组件
            audioElement: null,
            // 当前播放的中心频谱
            playCentral: null,
            // 播放字节
            currentBufferSource: null,
            // 所选下变频中心频率
            frequencyNumInput: '0',
            // 所选下变频中心频率
            frequencyNum: 0,
            // 全频率参数设置
            frequencySet: { title: "全频率设置", open: false, data: [] },
            // 是否开始获取中心频率
            showLine: false,
            // 移动距离
            linePosition: 0,
            // 音频数据
            audioUrls: [],
            // 音频数据缓冲队列
            audioBufferQueue: [],
            // 音频时长，初始值为null
            audioDuration: null,




            audio: '',
            // websiteUrl: 'https://open.ys7.com/jssdk/theme.html?url=ezopen://open.ys7.com/AB7723774/1.hd.live&accessToken=ar.51nh8qcdar7f092r3v558s4e5qvno5hg-2vehii7agm-16f45n0-tvdypacou&id=ysopen',
            // audio: '',
            audioContext: new (window.AudioContext || window.webkitAudioContext)(), // 创建AudioContext
            radioNum: 0,
            xAxisData: [],
            seriesData: [],
            dynamicComponent: null, // 动态组件的名称
            queryParams: {
                locatedAddress: null,
                name: null,
                radio: null,
            },
            radioCode: null,
            wsArr: [ ],
            frequencyDataMin: {
                central: 0,
                need_points: 0,
                bandwidth: 0,
                points: 0,
                data: "",
            },

            listAll: {
                station: [],
            },

            base64String: '',
            base64Arry: [],
            audioContext: null,
            audioBufferSources: [],
            currentAudioUrl: null,
            playing: false,
            //音频时长
            bufferTimer: null, // 定时器
            audioUrl: '', // 音频URL
            heartbeatInterval: null,//心跳
            start: {
            },
            central: 4500,//全频道
            bandwidth: 2,//带宽
            unit: {//单位
                central: 1000,//全频道
                bandwidth: 1000000,//带宽
                bandwidthGo: 1000,
            },
            timerActive: false,
            seconds: 0,

            bandwidthAdd: 400,//下变频增加的带宽大小


        }
    },
    created() {
        this.socketId = this.$uuid();
        this.initSocket();
    },
    mounted() {
        this.audioElement = new Audio();
    },
    methods: {
        // 启动socket
        initSocket() {
            const data = { cmd: "web-connect", data: { id: this.socketId } }
            const jsonData = JSON.stringify(data);
            const encodedData = encodeURIComponent(jsonData);
            const wsuri = this.url + '?' + encodedData;
            this.ws = new socketApi({
                url: wsuri, name: 'SDR', openSucceed: () => {
                    // 设置全频段回调函数
                    this.ws.setMsgBack({
                        cmd: 'sdr-result',
                        fun: this.fullResult
                    })
                    // 设置下变频回调函数
                    this.ws.setMsgBack({
                        cmd: 'channel-result',
                        fun: this.channelResult
                    })
                    // 设置音频回调函数
                    this.ws.setMsgBack({
                        cmd: 'wave-result',
                        fun: this.vdieoResult
                    })
                }
            })
        },

        // socket全频段回调函数
        fullResult(result) {
            // 设置全频段有数据了
            let { central, bandwidth, points, data, resolution_ratio, device_id, max, max_index, task_id, task_item_id } = result.data;
            central /= 10 ** 3;
            bandwidth /= 10 ** 3;
            console.log("全频段数据:",result.data)
            this.frequencyData = { central, bandwidth, points, data, resolution_ratio, need_points: bandwidth }
        },

        // socket下变频回调函数
        channelResult(result) {
        console.log("下变频数据:",result)
            let { central, bandwidth } = result.data;
            const sdr = { ...result.data, need_points: bandwidth, audio: null }
            for (let i = 0; i < this.popUpData.length; i++) {
                if (this.popUpData[i].central == central) {
                    this.popUpData[i].frequencyData = sdr;
                }
            }
        },

        // socket音频回调函数
        vdieoResult(result) {
            let base64data = result.data.data;
            // 收到音频URL
            const audioUrl = base64PlayUrl(base64data)
            this.getAudioDuration(audioUrl);
            this.audioUrls.push(audioUrl);
            // 缓冲并播放音频
            this.bufferAndPlayAudio(audioUrl);
        },

        //获取音频时长
        getAudioDuration(audioUrl) {
            try {
                // 创建一个新的音频上下文
                const audioContext = new (window.AudioContext || window.webkitAudioContext)();
                // 使用 fetch 方法获取音频文件的 ArrayBuffer
                fetch(audioUrl).then(rs => {
                    rs.arrayBuffer().then(audioData => {
                        // 解码音频数据
                        audioContext.decodeAudioData(audioData).then(decodedData => {
                            // 获取音频时长（单位：秒）
                            this.audioDuration = decodedData.duration.toFixed(3); // 保留三位小数
                            // 关闭音频上下文
                            audioContext.close();
                        });
                    });
                });
            } catch (error) {
                console.error('Error getting audio duration:', error);
            }
        },

        // 缓冲并播放音频
        bufferAndPlayAudio(audioUrl) {
            if (!this.audioContext) this.audioContext = new AudioContext();
            // 下载音频数据
            fetch(audioUrl)
                .then(rs => rs.arrayBuffer())
                .then(audioData => this.audioContext.decodeAudioData(audioData))
                .then(decodedData => {
                    // 将解码后的音频数据放入缓冲队列
                    this.audioBufferQueue.push(decodedData);
                    // 检查是否需要开始播放
                    if (!this.bufferTimer) {
                        // 如果定时器不存在，启动一个新的
                        this.bufferTimer = setTimeout(this.playCachedAudio.bind(this), 3000); // 5秒后播放
                    }
                })
                .catch(error => {
                    console.error('Error buffering and playing audio:', error);
                });
        },

        // 启动音频
        playCachedAudio() {
            if (this.audioBufferQueue.length === 0) return;
            const buffer = this.audioBufferQueue.shift(); // 从缓冲队列中取出一个音频数据
            // 创建音频源
            const source = this.audioContext.createBufferSource();
            source.buffer = buffer;

            // 连接到音频输出
            source.connect(this.audioContext.destination);

            // 播放音频
            source.start();

            // 设置定时器，以便在下一个音频片段结束后播放下一个
            this.bufferTimer = setTimeout(this.playCachedAudio.bind(this), buffer.duration * 1000);
        },

        // 启动全频段
        fullStart(parmars) {
            const data = {
                // 本机连接的唯一标识
                id: this.socketId,
                radioStationCode: parmars.radioStationCode,
                data: { ...this.sendParmars, central: parmars.central, bandwidth: parmars.bandwidth }
            }
            ffbStart(data).then(response => {//发送全频道
                if (response.code == 200) {
                    // 启动了全频段
                    this.isStart = true;
                    // 记录本次启动的参数 后面停止的时候需要用到
                    this.startObj = data;
                    // 重置下变频
                    this.popUpData = [];
                    // 启动一个与全频段相同中心频率的下变频
                    this.addPopUpData(parmars);
                    // this.$message.success("启动成功！");
                }
            });
        },
        // 创建一个下变频
        addPopUpData(parmars) {
            let { radioStationCode, central } = parmars;
            if (!radioStationCode) radioStationCode = this.startObj.radioStationCode;
            // 每次点击按钮，向数组中添加新的组件数据frequencyNum
            // 创建一个下变频窗口
            const channelObj = { id: this.socketId, radioStationCode, central, frequencyData: null }
            // 如果下变频最后一个不存在id则替换最后一个,因为初始化的时候会给一个空的下变频
            if(this.popUpData.length == 0){
                this.popUpData.push(channelObj);
            } else if (!this.popUpData[this.popUpData.length - 1].id) {
                this.popUpData[this.popUpData.length - 1] = channelObj
            } else {
                this.popUpData.push(channelObj);
            }
            this.postChannelStart(channelObj);//发送下变频
        },

        // 启动下变频
        postChannelStart(channelObj) {
            const { id, radioStationCode, central } = channelObj;
            if (this.isStart) {
                const parmary = {
                    id, radioStationCode,
                    data: {
                        ...this.sendParmars, central: central,
                        // 下变频带宽默认值、下变频采样率默认值、采集数据点的数量固定值
                        bandwidth: 12000, sample_frequence: 12000, points: 256
                    }
                }
                channelStart(parmary).then(rs => {
                    if (rs.code == 200) this.$message.success("下变频启动成功");
                });
            }
        },
        // 下变频点击GO按钮
        go(channelObj) {
            if (!this.isStart) {
                this.$message.info('请先启动全频段!');
                return;
            }
            for (let i = 0; i < this.popUpData.length; i++) {
                if (this.popUpData[i].id === channelObj.id) {
                    // 停止播放下变频
                    this.postPlayStop(this.popUpData[i].central);
                    // 变更下变频对应的中心频率
                    this.popUpData[i].central = channelObj.central;
                }
            }
            if (this.isStart) {
                const parmary = {
                    id: this.socketId, radioStationCode: this.startObj.radioStationCode,
                    data: { ...channelObj, type: "channel" }
                }
                // 变更下变频
                channelStart(parmary).then(response => { if (response.code != 200) { this.$message.error('下变频变更失败!') } });
            }
        },


        // 下变频点击播放回调
        playStart(channelObj) {
            // 如果和旧的中心频率相同就停止播放、否则就开启新的播放下变频
            if (this.playCentral == channelObj.central) {
                this.postPlayStop(channelObj);
                this.pauseAudio();
                this.playCentral = null;
            } else {
                //开启需要将新值赋给旧值
                this.playCentral = channelObj.central;
                this.postPlayStart(channelObj)
                if (!this.currentBufferSource) {
                    // 如果当前没有音频源，尝试播放下一个
                    this.connectAndPlayAudio();
                } else {
                    // 暂停后恢复播放
                    this.currentBufferSource.start(0, this.audioContext.currentTime);
                }
            }
        },

        // 开始播放下变频
        postPlayStart(channelObj) {
            const data = {
                id: this.socketId, radioStationCode: this.startObj.radioStationCode,
                data: { ...channelObj }
            }
            playStart(data).then(response => {
                if (response.code == 200) {
                    this.$modal.msgSuccess("发送成功");
                    this.audioPlay = true
                }
            });
        },

        // 停止播放下变频
        postPlayStop(channelObj) {
            if (!this.audioPlay) return;
            const parmary = { id: this.socketId, radioStationCode: this.startObj.radioStationCode, data: { ...channelObj } }
            this.audioPlay = false;
            this.audioElement.pause();
            playStop(parmary).then(response => {
                if (response.code != 200) this.$message.error('下变频停止播放失败!');
            });
        },
        // 播放
        connectAndPlayAudio() {
            if (this.audioBufferSources.length === 0) return;
            // 移除前一个缓冲的音频源
            if (this.currentBufferSource) {
                this.currentBufferSource.disconnect();
            }
            // 衔接音频数据
            const firstSource = this.audioBufferSources[0];
            this.currentBufferSource = firstSource;
            this.audioBufferSources.shift();
            if (this.audioBufferSources.length > 0) {
                // 缓冲1秒钟
                const nextSource = this.audioBufferSources[0];
                const currentTime = this.audioContext.currentTime;
                nextSource.start(currentTime + 1);
            }
            // 播放音频
            this.currentBufferSource.connect(this.audioContext.destination);
            this.currentBufferSource.start();
        },

        // 清空播放缓存
        pauseAudio() {
            // 清除缓冲定时器
            clearTimeout(this.bufferTimer);
            // 停止当前音频源
            if (this.currentBufferSource) {
                this.currentBufferSource.stop();
            }
            this.audioBufferQueue = [], // 音频数据缓冲队列
                this.bufferTimer = null, // 定时器
                this.audioDuration = null // 音频时长，初始值为null
            this.audioUrl = []
            this.audioContext = null
            this.audioBufferSources = []
            this.currentBufferSource = null

        },

        // 停止全频段
        fullStop() {
            // 停止所有下变频
            this.stopAllChannel();

            // 停止全频段
            ffbStop(this.startObj).then(response => {
                this.startObj = null;
                if (response.code == 200) {
                    this.isStart = false;
                    this.$message.success("已停止")
                }
            });
        },

        //失去聚焦计算刻度线位置
        calculateWire() {
            this.frequencyNumInput = this.frequencyNum + ''
        },

        // 获取点击位置相对于容器的偏移量
        showLineWay(event) {
            const offsetX = event.clientX - event.target.getBoundingClientRect().left;
            this.showLine = true;
            this.linePosition = offsetX;
        },

        // 创建下变频
        belowAddPopUpData() {
            let central = this.frequencyNum * 10 ** 6;
            let radioStationCode = this.startObj.radioStationCode;
            if (this.isStart) this.addPopUpData({ central, radioStationCode });
        },

        // 关闭下变频
        closeDialogPopUp(channelObj,index) {
            this.popUpData.splice(index,1)
            if(!channelObj) return;
            let channel = JSON.parse(JSON.stringify(channelObj))
            delete channel.data;
            delete channel.audio;
            const parmary = { radioStationCode: this.startObj.radioStationCode, id: this.startObj.id, data: { ...channel, type: "channel" } }
            channelStop(parmary).then(response => {
                if (response.code != 200) this.$message.info(`${channel.central}下变频结束失败!`)
            });
        },

        //销毁全部下变频数据
        stopAllChannel() {
            if (!this.startObj) return;
            //关闭所有下变频
            for (let i = 0; i < this.popUpData.length; i++) {
                const { id, radioStationCode, frequencyData } = this.popUpData[i];
                let params = JSON.parse(JSON.stringify(frequencyData));
                delete params.data;
                delete params.audio;
                const channelObj = { ...params, id, radioStationCode }
                this.closeDialogPopUp(channelObj);
            }
        },
















        // 结束下变频
        postChannelStop(val) {
            const data = {
                radioStationCode: this.startObj.radioStationCode,
                id: this.startObj.id,
                data: {
                    "type": "channel",
                    "central": val * this.unit.central
                }
            }
            channelStop(data).then(response => {
                if (response.code == 200) {
                    // this.$modal.msgSuccess("发送成功");
                }
            });
        },

        // 设置中心频率
        setNumber(num) {
            this.frequencyNum = (num / 1000).toFixed(3);
        },
    },
    // 在Vue组件的beforeDestroy生命周期钩子中清除定时器
    beforeDestroy() {
        if (this.ws) this.ws.close();
        clearInterval(this.heartbeatInterval);
    },
};
</script>


<style rel="stylesheet/scss" lang="scss" scoped>
.frequency-message-minor {
    .frequency-headline {
        background: linear-gradient(to right, #313B53, #272F43);
        height: 45px;
        line-height: 52px;
        padding-left: 10px;
        border-radius: 15px 15px 0 0;
        color: #9A9DAA;
        font-weight: 700;
    }

}

.fry-box {
    background: #171D2C;
    width: 100%;
    padding: 10px;
    border-radius: 50px;
}

.overall-set {
    cursor: pointer;
    margin-right: 30px;
    margin-left: 20px;

    img {
        width: 30px;
        margin-right: 5px;
    }

    color: #2CA6E0;
    font-size: 16px;
}

.zt-sdr {
    margin-left: 30px;

    img {
        width: 25px;
        margin-right: 5px;
    }

    .sdr-dian {
        font-size: 30px;
    }

    .sdr-text {
        margin-left: 5px;
        font-size: 16px;
    }

    color: #74C8CE;
}

.zt-data {
    // margin-left: 30px;
    margin-left: auto;
    margin-right: 20px;

    img {
        width: 20px;
        margin-right: 5px;
    }

    color: #fff;
}


.container {
    position: relative;
    //   height: 100px;
    //   width: 200px;
    //   background-color: #f0f0f0;
}

.line {
    position: absolute;
    left: 50%;
    top: 10%;
    transform: translateX(-50%);
    width: 2px;
    height: 62%;
    background-color: #FFE355;
    pointer-events: none;
    /* 防止线条遮挡点击事件 */
}

.h-num-input {
    appearance: none;
    border: none;
    background: none;
    margin: 0;
    padding: 0;
    outline: none;
    font: inherit;
    text-align: inherit;
    color: inherit;
    width: 65px;
    margin-left: 10px;

}

.h-num-input[type=number]::-webkit-inner-spin-button,
.h-num-input[type=number]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
</style>